home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Developer / BBFig / Source / YapApp.m < prev    next >
Text File  |  1994-05-09  |  10KB  |  355 lines

  1. /*
  2.  *  YapApp.m
  3.  *  Author: Ali Ozer
  4.  *  Created: Mar 89 for 0.9
  5.  *  Modified: Jul & Aug 89 for 1.0
  6.  *  Modified: Aug 90 for 2.0.
  7.  *  For BBFig to deo BoundingBox computation....
  8.  *  Modified: Jan 92 for BBFig by Izumi Ohzawa (izumi@pinoko.berkeley.edu)
  9.  *  Added Preferences: 92-05-14 Izumi Ohzawa.
  10.  *
  11.  *  YapApp is the application class used in Yap. It implements the
  12.  *  central functionality of coordinating the output and document
  13.  *  windows, opening documents, etc...
  14.  *
  15.  *  You may freely copy, distribute and reuse the code in this example.
  16.  *  NeXT disclaims any warranty of any kind, expressed or implied,
  17.  *  as to its fitness for any particular use.
  18.  */
  19.  
  20. #import "YapApp.h"
  21. #import "YapDocument.h"
  22. #import "YapOutput.h"
  23.  
  24. #import <stdio.h>
  25. #import <defaults/defaults.h>
  26. #import <appkit/nextstd.h>     // MIN, MAX, etc
  27. #import <appkit/OpenPanel.h>
  28. #import <appkit/Text.h>
  29. #import <appkit/SavePanel.h>
  30. #import <appkit/ScrollView.h>
  31. #import <appkit/TextField.h>
  32. #import <appkit/Button.h>
  33. #import <objc/List.h>
  34. #import <sys/param.h>
  35.  
  36. @implementation YapApp
  37.  
  38. - appDidInit:sender
  39. {
  40.     static NXDefaultsVector BBFigDefaults = {
  41.         {"BBoxMargin", "2"},
  42.         {NULL}
  43.     };
  44.  
  45.     NXRegisterDefaults([NXApp appName], BBFigDefaults);
  46.     bbmargin = atoi(NXGetDefaultValue([NXApp appName], "BBoxMargin"));
  47.     if(bbmargin < 0) bbmargin = 0;
  48.     if(bbmargin >20) bbmargin = 20;
  49.     return self;
  50. }
  51.  
  52. - outputView   
  53. {
  54.     return outputView;
  55. }
  56.  
  57. - outputWindow
  58. {
  59.     return [outputView window];
  60. }
  61.  
  62. #define DEFAULTWIDTH 612
  63. #define DEFAULTHEIGHT 792
  64. #define MINSIZE 72
  65. #define MAXSIZE 3600
  66.  
  67. /*
  68.  * Here we have a handle to the output window, created in IB. We create
  69.  * the scroll and the yap output views and add them to this window.
  70.  */
  71. - setOutputWindow:anObject 
  72. {
  73.     NXRect initFrame = {{0.0, 0.0}, {DEFAULTWIDTH, DEFAULTHEIGHT}};
  74.  
  75.     id scrollView = [ScrollView new];
  76.  
  77.     outputView = [[YapOutput allocFromZone:[self zone]] initFrame:&initFrame];
  78.  
  79.     [anObject setBackgroundGray:NX_WHITE];
  80.     [anObject removeFromEventMask:NX_KEYDOWNMASK|NX_KEYUPMASK];
  81.     
  82.     [scrollView setBorderType:NX_NOBORDER];
  83.     [scrollView setHorizScrollerRequired:YES];
  84.     [scrollView setVertScrollerRequired:YES];
  85.  
  86.     [anObject setContentView:scrollView];
  87.     [scrollView setDocView:outputView];
  88.  
  89.     [anObject setDelegate:self]; // So we can get windowWillResize:toSize:
  90.     [anObject display];
  91.  
  92.     [NXApp updateOutputWindowSize];
  93.  
  94.     return self;
  95. }
  96.  
  97. /*
  98.  * windowWillResize:toSize: is a delegate method that gets called
  99.  * when a window is being resized. In our case, we want to limit the user
  100.  * from growing the output window to a size that is greater than that of the
  101.  * view.
  102.  */
  103. - windowWillResize:sender toSize:(NXSize *)sz
  104. {
  105.     if (sz->width > maxWindowSize.width) sz->width = maxWindowSize.width;
  106.     if (sz->height > maxWindowSize.height) sz->height = maxWindowSize.height;
  107.  
  108.     return self;
  109. }   
  110.  
  111. /*
  112.  * updateOutputWindowSize should be called after the size of the output view is
  113.  * changed. It simply makes sure the window isn't too big for the view. If the
  114.  * window is indeed to big, it is resized smaller.
  115.  */
  116. - updateOutputWindowSize
  117. {
  118.     NXRect frame, content;
  119.    
  120.     // The next few lines allow us to get the window size for the window
  121.     // containing a ScrollView and the yap output view.
  122.  
  123.     [[self outputView] getFrame:&frame];
  124.     [ScrollView getFrameSize:&maxWindowSize forContentSize:&(frame.size)
  125.             horizScroller:YES vertScroller:YES borderType:NX_NOBORDER];
  126.  
  127.     // sizeWindow:: wants window size in content area; so we can use the
  128.     // maxWindowSize from above. But to compare it to the window frame,
  129.     // we first need to get the content area for the current frame.
  130.  
  131.     [[self outputWindow] getFrame:&frame];      
  132.     [Window getContentRect:&content forFrameRect:&frame 
  133.         style:[[self outputWindow] style]];
  134.  
  135.     if (content.size.width > maxWindowSize.width ||
  136.     content.size.height > maxWindowSize.height) { 
  137.     [[self outputWindow] 
  138.         sizeWindow:MIN(maxWindowSize.width, content.size.width)
  139.               :MIN(maxWindowSize.height, content.size.height)];
  140.     }
  141.  
  142.     // Now we go from the content size to the window frame size, which is 
  143.     // what we will use in windowWillResize:toSize:
  144.  
  145.     content.size = maxWindowSize;
  146.     [Window getFrameRect:&frame forContentRect:&content
  147.         style:[[self outputWindow] style]];
  148.  
  149.     maxWindowSize = frame.size;
  150.  
  151.     return self;
  152. }
  153.  
  154. /*
  155.  * newDocument simply creates a new Yap document and displays it.
  156.  */
  157. - newDocument:sender
  158. {
  159.     [YapDocument new];
  160.  
  161.     return self;
  162. }
  163.  
  164. /*
  165.  * openDocument gets a file name from the user, creates a new document window,
  166.  * and loads the specified file into it.
  167.  */
  168. - openDocument:sender
  169. {
  170.     // Allow ps, eps, and any other extension not handled by other apps.
  171.     // Note that "" should come first in the list.
  172.     static const char *const yapTypes[] = {"", "ps", "eps", NULL};  
  173.  
  174.     if ([[OpenPanel new] runModalForTypes:yapTypes]) {
  175.     if ([YapDocument newFromFile:[[OpenPanel new] filename]] == nil) {
  176.         NXRunAlertPanel (NULL, "Could not open file.", "OK", NULL, NULL);
  177.     }
  178.     }
  179.  
  180.     return self;
  181. }
  182.  
  183. /*
  184.  * appOpenFile:type: is invoked by Workspace when the user double-clicks
  185.  * on a file Yap is prepared to accept. By default, Yap is not prepared to open
  186.  * any files, however, it can easily be made to open files of certain type
  187.  * through the IB project inspector.
  188.  */
  189. - (int)appOpenFile:(const char *)path type:(const char *)type
  190. {
  191.     if ([YapDocument newFromFile:path] == nil) return NO;
  192.     else return YES;
  193. }
  194.  
  195. /*
  196.  * The following method indicates that Yap is ready to open multiple
  197.  * files at one time.
  198.  */
  199. - (BOOL)appAcceptsAnotherFile:sender
  200. {
  201.     return YES;
  202. }
  203.  
  204. /*
  205.  * Methods to load .nib files for the various panels.
  206.  */
  207. - showInfo:sender
  208. {
  209.     if (!infoPanel) {
  210.     [self loadNibSection:"Info.nib" owner:self withNames:NO];
  211.     }
  212.     [infoPanel makeKeyAndOrderFront:sender];
  213.     return self;
  214. }
  215.  
  216. - showHelp:sender
  217. {
  218.     if (!helpPanel) {
  219.     [self loadNibSection:"Help.nib" owner:self withNames:NO];
  220.     }
  221.     [helpPanel makeKeyAndOrderFront:sender];
  222.     return self;
  223. }
  224.  
  225. - showPrefs:sender
  226. {
  227.     if (!prefsPanel) {
  228.     [self loadNibSection:"Prefs.nib" owner:self withNames:NO];
  229.     [self updatePreferencesPanel:sender];
  230.     }
  231.     [prefsPanel makeKeyAndOrderFront:sender];
  232.     return self;
  233. }
  234.  
  235.  
  236. - bbmarginSliderAction:sender
  237. {
  238.     /* just reflect the slider value into field */
  239.     [marginBBoxField setIntValue:[sender intValue]];
  240.     return self;
  241. }
  242.  
  243. - (int)bbMargin
  244. {
  245.     return bbmargin;
  246. }
  247.  
  248. /*
  249.  * updatePreferencesPanel: is used to copy the existing situation into
  250.  * the Prefences panel.
  251.  */
  252. - updatePreferencesPanel:sender
  253. {
  254.     NXRect outputFrame;
  255.  
  256.     [[self outputView] getFrame:&outputFrame];
  257.     [outputWidthField setFloatValue:NX_WIDTH(&outputFrame)];
  258.     [outputHeightField setFloatValue:NX_HEIGHT(&outputFrame)];
  259.     [showCacheButton setState:[[self outputView] isCacheShown]];
  260.     [clearCacheButton setState:[[self outputView] isCacheCleared]];
  261.  
  262.     [showGridButton setState:[[self outputView] isMeshON]];
  263.     [computeBBoxButton setState:[[self outputView] isFigureBB]];
  264.     [marginBBoxSlider setIntValue:bbmargin];
  265.     [marginBBoxField setIntValue:bbmargin];
  266.  
  267.     [outputWidthField selectText:sender];
  268.  
  269.     return self;
  270. }
  271.  
  272. /*
  273.  * okPreferencesPanel: causes the values in Preferences to be read into the
  274.  * application and applied to the various objects.
  275.  */
  276. - okPreferencesPanel:sender
  277. {
  278. char strbuf[80];
  279.     NXCoord desiredWidth, desiredHeight;
  280.  
  281.     desiredWidth = [outputWidthField floatValue];
  282.     if (desiredWidth < MINSIZE || desiredWidth > MAXSIZE) {
  283.     desiredWidth = MIN(MAX(desiredWidth, MINSIZE), MAXSIZE);
  284.     [outputWidthField setFloatValue:desiredWidth];
  285.     }
  286.     desiredHeight = [outputHeightField floatValue];
  287.     if (desiredHeight < MINSIZE || desiredHeight > MAXSIZE) {
  288.     desiredHeight = MIN(MAX(desiredHeight, MINSIZE), MAXSIZE);
  289.     [outputHeightField setFloatValue:desiredHeight];
  290.     }
  291.  
  292.     [[self outputView] sizeTo:desiredWidth :desiredHeight];
  293.     [self updateOutputWindowSize];
  294.  
  295.     [[self outputView] setCacheShown:[showCacheButton state]];
  296.     [[self outputView] setCacheCleared:[clearCacheButton state]];
  297.     [[self outputView] setMeshON:[showGridButton state]];
  298.     [[self outputView] setFigureBB:[computeBBoxButton state]];
  299.     bbmargin = [marginBBoxSlider intValue];
  300.     [marginBBoxField setIntValue:bbmargin];
  301.     sprintf(strbuf, "%d\0", bbmargin);
  302.     NXWriteDefault ([NXApp appName], "BBoxMargin", strbuf);
  303.  
  304.     [[sender window] orderOut:sender];
  305.     [outputWidthField selectText:sender];
  306.  
  307.     return self;
  308. }
  309.  
  310. /* This method code taken from Draw.app source */
  311. - terminate:sender
  312. /*
  313.  * Overridden to be sure all documents get an opportunity to be saved
  314.  * before exiting the program.
  315.  */
  316. {
  317.     int count, choice;
  318.     id window, document;
  319.  
  320.     count = [windowList count];        /* windowList is in NXApp which this one is */
  321.     while (count--) {
  322.     window = [windowList objectAt:count];
  323.      document = [window delegate];
  324.     if ([window isDocEdited]) {
  325.         choice = NXRunAlertPanel("Quit", "You have unsaved documents.",
  326.                          "Review Unsaved", "Quit Anyway", "Cancel");
  327.         if (choice == NX_ALERTOTHER)  {
  328.         return self;
  329.         } else if (choice == NX_ALERTDEFAULT) {
  330.         count = [windowList count];
  331.         while (count--) {
  332.             window = [windowList objectAt:count];
  333.             document = [window delegate];
  334.             if ([document respondsTo:@selector(windowWillClose:action:)]) {
  335.             if ([document windowWillClose:window action:"Quit"]) {
  336.                 [window close];
  337.             } else {
  338.                 return self;
  339.             }
  340.             }
  341.         }
  342.         }
  343.         break;
  344.     }
  345.     }
  346.  
  347.     [super terminate:sender];
  348.  
  349.     return nil;
  350. }
  351.     
  352.  
  353. @end
  354.  
  355.